﻿using HDSmartCommunity.Models;
using HDSmartCommunity.Serial;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static HDSmartCommunity.Startup;

namespace HDSmartCommunity.BUS.MqttBUS
{
    public class MqttClientBUS
    {
        IMqttClient _client;
        MqttClientOptions _options;
        public MqttClientBUS()
        {
            FXMqttClient client = SerialServer.FXMqttClient;
            this._client = client.MqttClient;
            this._options = client.Options;
        }



        public async Task<ResponseMessage> PublicMessage(string Topic, string Message, int QuantityOfLevel)
        {
            if (SerialServer.Encry == 1)
            {
                Message = RSAEncrypt(SerialServer.publickey, Message);
            }
            ResponseMessage response = await PublicAsyncMessage(Topic, Message, QuantityOfLevel);
            return response;
        }
        private async Task<ResponseMessage> PublicAsyncMessage(string Topic, string Message, int QuantityOfLevel)
        {
            ResponseMessage message = new ResponseMessage() { errcode = 0, errmsg = "", data = null };
            try
            {
                if (!this._client.IsConnected)
                {
                    await this._client.ConnectAsync(_options).ConfigureAwait(false);
                }
                await this._client.PublishAsync(new MQTTnet.MqttApplicationMessage()
                {
                    Payload = System.Text.UTF8Encoding.UTF8.GetBytes(Message),
                    QualityOfServiceLevel = (MQTTnet.Protocol.MqttQualityOfServiceLevel)QuantityOfLevel,
                    Topic = Topic,
                    Retain = true
                }).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());

                message.errcode = 1;
#if DEBUG
                message.errmsg = e.ToString();
#else
                message.errmsg = $"发送{Topic}主题错误";
#endif
                return message;
            }
            return message;
        }

        public string RSAEncrypt(string m_strEncryptString)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(SerialServer.publickey);
            byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString);
            return Convert.ToBase64String(provider.Encrypt(bytes, false));
        }

        public string RSAEncrypt(string xmlPublicKey, string m_strEncryptString)
        {
            /* RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
             provider.FromXmlString(xmlPublicKey);
             byte[] bytes = new UnicodeEncoding().GetBytes(m_strEncryptString);
             return Convert.ToBase64String(provider.Encrypt(bytes, false));*/
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] data = new UnicodeEncoding().GetBytes(m_strEncryptString);       //要加密的数据
            rsa.FromXmlString(xmlPublicKey);
            int keySize = rsa.KeySize / 8;
            int bufferSize = keySize - 11;
            byte[] buffer = new byte[bufferSize];
            MemoryStream msInput = new MemoryStream(data);
            MemoryStream msOuput = new MemoryStream();
            int readLen = msInput.Read(buffer, 0, bufferSize);
            while (readLen > 0)
            {
                byte[] dataToEnc = new byte[readLen];
                Array.Copy(buffer, 0, dataToEnc, 0, readLen);
                byte[] encData = rsa.Encrypt(dataToEnc, false);
                msOuput.Write(encData, 0, encData.Length);
                readLen = msInput.Read(buffer, 0, bufferSize);
            }
            msInput.Close();
            byte[] result = msOuput.ToArray();    //得到加密结果
            msOuput.Close();
            rsa.Clear();
            return Convert.ToBase64String(result);
        }
    }
}
